{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn as sns\n",
    "import random\n",
    "import time\n",
    "import collections\n",
    "from tqdm import tqdm\n",
    "sns.set()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "def build_dataset(words, n_words, atleast=1):\n",
    "    count = [['PAD', 0], ['GO', 1], ['EOS', 2], ['UNK', 3]]\n",
    "    counter = collections.Counter(words).most_common(n_words)\n",
    "    counter = [i for i in counter if i[1] >= atleast]\n",
    "    count.extend(counter)\n",
    "    dictionary = dict()\n",
    "    for word, _ in count:\n",
    "        dictionary[word] = len(dictionary)\n",
    "    data = list()\n",
    "    unk_count = 0\n",
    "    for word in words:\n",
    "        index = dictionary.get(word, 0)\n",
    "        if index == 0:\n",
    "            unk_count += 1\n",
    "        data.append(index)\n",
    "    count[0][1] = unk_count\n",
    "    reversed_dictionary = dict(zip(dictionary.values(), dictionary.keys()))\n",
    "    return data, count, dictionary, reversed_dictionary"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "with open('shakespeare.txt') as fopen:\n",
    "    shakespeare = fopen.read()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "vocabulary_size = len(list(set(shakespeare)))\n",
    "data, count, dictionary, rev_dictionary = build_dataset(shakespeare, vocabulary_size)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "GO = dictionary['GO']\n",
    "PAD = dictionary['PAD']\n",
    "EOS = dictionary['EOS']\n",
    "UNK = dictionary['UNK']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "class Generator:\n",
    "    def __init__(self, size_layer, num_layers, embedded_size,\n",
    "                 from_dict_size, to_dict_size, learning_rate, batch_size):\n",
    "        \n",
    "        def cells(reuse=False):\n",
    "            return tf.nn.rnn_cell.GRUCell(size_layer,reuse=reuse)\n",
    "        \n",
    "        self.X = tf.placeholder(tf.int32, [None, None])\n",
    "        self.Y = tf.placeholder(tf.int32, [None, None])\n",
    "        self.X_seq_len = tf.count_nonzero(self.X, 1, dtype=tf.int32)\n",
    "        self.Y_seq_len = tf.count_nonzero(self.Y, 1, dtype=tf.int32)\n",
    "        batch_size = tf.shape(self.X)[0]\n",
    "        \n",
    "        encoder_embedding = tf.Variable(tf.random_uniform([from_dict_size, embedded_size], -1, 1))\n",
    "        decoder_embedding = tf.Variable(tf.random_uniform([to_dict_size, embedded_size], -1, 1))\n",
    "        self.cells = tf.nn.rnn_cell.MultiRNNCell([cells() for _ in range(num_layers)])\n",
    "        self.encoder_state = self.cells.zero_state(\n",
    "            dtype = tf.float32, batch_size = tf.shape(self.X)[0]\n",
    "        )\n",
    "        \n",
    "        encoder_out, encoder_state = tf.nn.dynamic_rnn(\n",
    "            cell = self.cells, \n",
    "            inputs = tf.nn.embedding_lookup(encoder_embedding, self.X),\n",
    "            sequence_length = self.X_seq_len,\n",
    "            initial_state = self.encoder_state,\n",
    "            dtype = tf.float32)\n",
    "        \n",
    "        main = tf.strided_slice(self.Y, [0, 0], [batch_size, -1], [1, 1])\n",
    "        decoder_input = tf.concat([tf.fill([batch_size, 1], GO), main], 1)\n",
    "        dense = tf.layers.Dense(to_dict_size)\n",
    "        attention_mechanism = tf.contrib.seq2seq.LuongAttention(num_units = size_layer, \n",
    "                                                                    memory = encoder_out,\n",
    "                                                                    memory_sequence_length = self.X_seq_len)\n",
    "        \n",
    "        decoder_cells = tf.contrib.seq2seq.AttentionWrapper(\n",
    "            cell = tf.nn.rnn_cell.MultiRNNCell([cells() for _ in range(num_layers)]), \n",
    "                attention_mechanism = attention_mechanism,\n",
    "                attention_layer_size = size_layer)\n",
    "        \n",
    "        training_helper = tf.contrib.seq2seq.TrainingHelper(\n",
    "                inputs = tf.nn.embedding_lookup(decoder_embedding, decoder_input),\n",
    "                sequence_length = self.Y_seq_len,\n",
    "                time_major = False)\n",
    "        training_decoder = tf.contrib.seq2seq.BasicDecoder(\n",
    "                cell = decoder_cells,\n",
    "                helper = training_helper,\n",
    "                initial_state = decoder_cells.zero_state(batch_size, tf.float32).clone(cell_state=encoder_state),\n",
    "                output_layer = dense)\n",
    "        training_decoder_output, self.training_state, _ = tf.contrib.seq2seq.dynamic_decode(\n",
    "                decoder = training_decoder,\n",
    "                impute_finished = True,\n",
    "                maximum_iterations = tf.reduce_max(self.Y_seq_len))\n",
    "        self.training_logits = training_decoder_output.rnn_output\n",
    "        \n",
    "        predicting_helper = tf.contrib.seq2seq.GreedyEmbeddingHelper(\n",
    "                embedding = decoder_embedding,\n",
    "                start_tokens = tf.tile(tf.constant([GO], dtype=tf.int32), [batch_size]),\n",
    "                end_token = EOS)\n",
    "        predicting_decoder = tf.contrib.seq2seq.BasicDecoder(\n",
    "                cell = decoder_cells,\n",
    "                helper = predicting_helper,\n",
    "                initial_state = decoder_cells.zero_state(batch_size, tf.float32).clone(cell_state=encoder_state),\n",
    "                output_layer = dense)\n",
    "        predicting_decoder_output, self.predict_state, _ = tf.contrib.seq2seq.dynamic_decode(\n",
    "                decoder = predicting_decoder,\n",
    "                impute_finished = True,\n",
    "                maximum_iterations = tf.reduce_max(self.X_seq_len))\n",
    "        self.predicting_ids = predicting_decoder_output.sample_id\n",
    "        print(self.training_state, self.predict_state)\n",
    "        \n",
    "        masks = tf.sequence_mask(self.Y_seq_len, tf.reduce_max(self.Y_seq_len), dtype=tf.float32)\n",
    "        self.cost = tf.contrib.seq2seq.sequence_loss(logits = self.training_logits,\n",
    "                                                     targets = self.Y,\n",
    "                                                     weights = masks)\n",
    "        self.optimizer = tf.train.AdamOptimizer(learning_rate = learning_rate).minimize(self.cost)\n",
    "        \n",
    "        y_t = tf.argmax(self.training_logits,axis=2)\n",
    "        y_t = tf.cast(y_t, tf.int32)\n",
    "        self.prediction = tf.boolean_mask(y_t, masks)\n",
    "        mask_label = tf.boolean_mask(self.Y, masks)\n",
    "        correct_pred = tf.equal(self.prediction, mask_label)\n",
    "        correct_index = tf.cast(correct_pred, tf.float32)\n",
    "        self.accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "learning_rate = 0.001\n",
    "batch_size = 32\n",
    "sequence_length = 64\n",
    "epoch = 3000\n",
    "num_layers = 2\n",
    "size_layer = 256\n",
    "possible_batch_id = range(len(data) - sequence_length - 1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "AttentionWrapperState(cell_state=(<tf.Tensor 'decoder/while/Exit_4:0' shape=(?, 256) dtype=float32>, <tf.Tensor 'decoder/while/Exit_5:0' shape=(?, 256) dtype=float32>), attention=<tf.Tensor 'decoder/while/Exit_6:0' shape=(?, 256) dtype=float32>, time=<tf.Tensor 'decoder/while/Exit_7:0' shape=() dtype=int32>, alignments=<tf.Tensor 'decoder/while/Exit_8:0' shape=(?, ?) dtype=float32>, alignment_history=(), attention_state=<tf.Tensor 'decoder/while/Exit_9:0' shape=(?, ?) dtype=float32>) AttentionWrapperState(cell_state=(<tf.Tensor 'decoder_1/while/Exit_4:0' shape=(?, 256) dtype=float32>, <tf.Tensor 'decoder_1/while/Exit_5:0' shape=(?, 256) dtype=float32>), attention=<tf.Tensor 'decoder_1/while/Exit_6:0' shape=(?, 256) dtype=float32>, time=<tf.Tensor 'decoder_1/while/Exit_7:0' shape=() dtype=int32>, alignments=<tf.Tensor 'decoder_1/while/Exit_8:0' shape=(?, ?) dtype=float32>, alignment_history=(), attention_state=<tf.Tensor 'decoder_1/while/Exit_9:0' shape=(?, ?) dtype=float32>)\n"
     ]
    }
   ],
   "source": [
    "tf.reset_default_graph()\n",
    "sess = tf.InteractiveSession()\n",
    "model = Generator(size_layer, num_layers, size_layer, len(dictionary), \n",
    "                len(dictionary), learning_rate,batch_size)\n",
    "sess.run(tf.global_variables_initializer())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "def train_random_batch():\n",
    "    LOST, ACCURACY = [], []\n",
    "    pbar = tqdm(range(epoch), desc = 'epoch')\n",
    "    batch_id = random.sample(possible_batch_id, batch_size)\n",
    "    batch_x = np.zeros((batch_size, sequence_length))\n",
    "    batch_y = np.zeros((batch_size, sequence_length + 1))\n",
    "    for n in range(sequence_length):\n",
    "        id1 = [data[k + n] for k in batch_id]\n",
    "        id2 = [data[k + n + 1] for k in batch_id]\n",
    "        batch_x[:,n] = id1\n",
    "        batch_y[:,n] = id2\n",
    "    batch_y[:,-1] = [EOS] * batch_size\n",
    "    batch_x = batch_x.astype('int32')\n",
    "    batch_y = batch_y.astype('int32')\n",
    "    initial_state, _ = sess.run([model.predict_state, model.optimizer], feed_dict = {model.X: batch_x,\n",
    "                                                                                    model.Y: batch_y})\n",
    "    initial_state = initial_state.cell_state\n",
    "    \n",
    "    for i in pbar:\n",
    "        batch_x = np.zeros((batch_size, sequence_length))\n",
    "        batch_y = np.zeros((batch_size, sequence_length + 1))\n",
    "        batch_id = random.sample(possible_batch_id, batch_size)\n",
    "        for n in range(sequence_length):\n",
    "            id1 = [data[k + n] for k in batch_id]\n",
    "            id2 = [data[k + n + 1] for k in batch_id]\n",
    "            batch_x[:,n] = id1\n",
    "            batch_y[:,n] = id2\n",
    "        batch_y[:,-1] = [EOS] * batch_size\n",
    "        accuracy, _, loss, initial_state = sess.run([model.accuracy, model.optimizer, \n",
    "                                                     model.cost, model.predict_state], \n",
    "                                       feed_dict = {model.X: batch_x, \n",
    "                                                    model.Y: batch_y,\n",
    "                                                    model.encoder_state: initial_state})\n",
    "        initial_state = initial_state.cell_state\n",
    "        ACCURACY.append(accuracy); LOST.append(loss)\n",
    "        pbar.set_postfix(cost = loss, accuracy = accuracy)\n",
    "    return LOST, ACCURACY"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "epoch: 100%|██████████| 3000/3000 [21:14<00:00,  2.37it/s, accuracy=0.986, cost=0.0703]\n"
     ]
    }
   ],
   "source": [
    "LOST, ACCURACY = train_random_batch()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 1080x360 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.figure(figsize = (15, 5))\n",
    "plt.subplot(1, 2, 1)\n",
    "EPOCH = np.arange(len(LOST))\n",
    "plt.plot(EPOCH, LOST)\n",
    "plt.xlabel('epoch')\n",
    "plt.ylabel('loss')\n",
    "plt.subplot(1, 2, 2)\n",
    "plt.plot(EPOCH, ACCURACY)\n",
    "plt.xlabel('epoch')\n",
    "plt.ylabel('accuracy')\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [],
   "source": [
    "def generate_based_sequence(length_sentence):\n",
    "    index = np.random.randint(0, len(data) - sequence_length - 1)\n",
    "    x = np.array([data[index:index + sequence_length]])\n",
    "    initial_state, ids = sess.run([model.predict_state,model.predicting_ids], \n",
    "                                  feed_dict = {model.X: x})\n",
    "    initial_state = initial_state.cell_state\n",
    "    ids = ids[0].tolist()\n",
    "    \n",
    "    while len(ids) < length_sentence:\n",
    "        initial_state, ids_ = sess.run([model.predict_state,model.predicting_ids], \n",
    "                                      feed_dict = {model.X: [ids[-sequence_length:]],\n",
    "                                                  model.encoder_state: initial_state})\n",
    "        initial_state = initial_state.cell_state\n",
    "        ids.extend(ids_[0].tolist())\n",
    "\n",
    "    return ''.join([rev_dictionary[i] for i in ids])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ut want their remedies.\n",
      "Cousin, I am tooung aftEOSt want their remedies.\n",
      "Cousin, I am tooung aft\n",
      "S am tooung aft\n",
      "t want their remedies.\n",
      "Cousin, I am tooung aft\n",
      "Suam tooung aft\n",
      "t want their remedies.\n",
      "Cousin, I am tooung aft\n",
      "Sunm tooung aft\n",
      "t want their remedies.\n",
      "Cousin, I am tooung aft\n",
      "Sund tooung aft\n",
      "t want their remedies.\n",
      "Cousin, I am tooung aft\n",
      "Sund tooung aft\n",
      "t want their remedies.\n",
      "Cousin, I am tooung aft\n",
      "Sund sooung aft\n",
      "t want their remedies.\n",
      "Cousin, I am tooung aft\n",
      "Sund seoung aft\n",
      "t want their remedies.\n",
      "Cousin, I am tooung aft\n",
      "Sund seEOSung aft\n",
      "t want their remedies.\n",
      "Cousin, I am tooung aft\n",
      "Sund seEOSung aft\n",
      "t want their remedies.\n",
      "Cousin, I am tooung aft\n",
      "Sund seEOSung aft\n",
      "t want their remedies.\n",
      "Cousin, I am tooung aft\n",
      "Sund seEOSung aft\n",
      "t want their remedies.\n",
      "Cousin, I am tooung aft\n",
      "Sund seEOSung aft\n",
      "t want their remedies.\n",
      "Cousin, I am tooung aft\n",
      "Sund seEOSung aft\n",
      "t want their remedies.\n",
      "Cousin, I am tooung aft\n",
      "Sund seEOSung aft\n",
      "t want their remedies.\n",
      "Cousin, I am tooung aft\n",
      "Sund seEOSung aft\n",
      "t want their remedies.\n",
      "Cousin, I am tooung aft\n",
      "Sund seEOS\n"
     ]
    }
   ],
   "source": [
    "print(generate_based_sequence(1000))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
